/*     Copyright (c) 2018, jymenu.com. All rights reserved.   */
package com.yunhaikeji.core.exception;

import com.yunhaikeji.core.web.ProcessResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

/**
 * GlobalExceptionHandler
 *
 * @author : zhuo
 * @date : 2018/8/3 20:35
 * @description :
 */
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {
    protected static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public ProcessResult httpRequestMethodNotSupportedException(HttpServletResponse response) {
        return ProcessResult.error("method 方法不支持").setCode("405");
    }

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    @ResponseBody
    public ProcessResult httpMediaTypeNotSupportedException(HttpServletResponse response) {
        return ProcessResult.error("不支持媒体类型").setCode("415");
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ProcessResult notFoundPage404(HttpServletResponse response) {
        return ProcessResult.error("未找到方法").setCode("404");
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ProcessResult argumentTypeMismatch(HttpServletResponse response) {
        return ProcessResult.error("参数类型不匹配").setCode("400");
    }

    @ExceptionHandler(value = ConstraintViolationException.class)
    public ProcessResult constraintViolationExceptionHandler(ConstraintViolationException e) {

        return ProcessResult.error(e.getConstraintViolations().stream()
                .map(ConstraintViolation::getMessageTemplate)
                .findFirst()
                .orElse(e.getMessage())
        ).setCode("999");
    }

    @ExceptionHandler(value = BindException.class)
    public ProcessResult bindExceptionHandler(BindException e) {

        return ProcessResult.error(e.getFieldErrors().stream()
                .map(FieldError::getDefaultMessage)
                .findFirst()
                .orElse(e.getMessage())
        ).setCode("999");
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ProcessResult methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {

        return ProcessResult.error(e.getBindingResult().getAllErrors().stream()
                .map(ObjectError::getDefaultMessage)
                .findFirst()
                .orElse(e.getMessage())
        ).setCode("999");
    }

    @ExceptionHandler(value = BadCredentialsException.class)
    public ProcessResult badCredentialsException(BadCredentialsException e) {
        throw e;
    }

    @ExceptionHandler(value = AccessDeniedException.class)
    public ProcessResult accessDeniedException(AccessDeniedException e) {
        throw e;
    }

    @ExceptionHandler(value = AuthenticationException.class)
    public ProcessResult authenticationExceptionHandler(AuthenticationException e) {
        return ProcessResult.error(e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ProcessResult defaultException(HttpServletResponse response, Exception e) {
        logger.error("error:", e);
        return ProcessResult.error("系统内部错误").setCode("500");
    }

}
